import os
import random
from datetime import datetime
from flask_mobility import Mobility
from flask import Flask, current_app, send_from_directory, redirect, url_for, _request_ctx_stack as stack
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash

from . import auth
from . import data
from . import course
from . import manage
from . import student
from . import professor

from . import config
from .models import User, Course, Timetable, Participant
from .database import init_app as init_database
from .avatar import init_app as init_avatar, generate_avatar

def create_app():
    # create and configure the app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        config.production if app.config['ENV'] == 'production' else config.develop)

    # ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    with app.app_context():
        Mobility(app)
        init_avatar(app)
        db = init_database(app)
        if ensure_admin_account(app, db):
            import_demo_data(db)

    app.register_blueprint(auth.bp)
    app.register_blueprint(data.bp)
    app.register_blueprint(course.bp)
    app.register_blueprint(manage.bp)
    app.register_blueprint(student.bp)
    app.register_blueprint(professor.bp)

    if app.config['MOBILE']:
        @app.before_request
        def before_request():
            ctx = stack.top
            if ctx is not None and hasattr(ctx, 'request'):
                ctx.request.MOBILE = True
                print("user_agent", ctx.request.user_agent)

    @app.route('/')
    def index():
        return redirect(url_for('auth.login'))

    @app.route('/avatars/<path:filename>')
    def get_avatar(filename):
        path = current_app.config['AVATARS_SAVE_PATH'] + '/avatars'
        return send_from_directory(path, filename)

    return app

def import_demo_data(db: SQLAlchemy):
    hashed_password = generate_password_hash('123456')

    users = [
        User(id=2, email='joy@demo.com', name='Sandip Saha Joy', role='professor',
             hashed_password=hashed_password, avatar=generate_avatar(random.randrange(10**5, 10**10)),
             age=45, gender='Male', address='6391 elgin St.celina Delaware 10299',
             post='Cognitive Data Scientist', key_ompetency='Computing Science',
             skill_points=['Computing Science', 'University of Alberta', 'Machine Learning', 'Deep Learning', 'Statistical Modeling', 'Computer Vision', 'Digital Image Processing']),
        User(id=3, email='steve@demo.com', name='Steve Ryan', role='professor',
             hashed_password=hashed_password, avatar=generate_avatar(random.randrange(10**5, 10**10)),
             age=48, gender='Male', address='6391 elgin St.celina Delaware 10299',
             post='Content Developer', key_ompetency='Desktop Operating Systems',
             skill_points=['Desktop Operating Systems', 'TCP/IP Networks', 'SharePoint Server', 'Cloud Technologies']),
        User(id=4, email='jennifer@demo.com', name='Jennifer Widom', role='professor',
             hashed_password=hashed_password, avatar=generate_avatar(random.randrange(10**5, 10**10)),
             age=48, gender='Female', address='6391 elgin St.celina Delaware 10299',
             post='Dean, School of Engineering', key_ompetency='Data Management',
             skill_points=['Data Management']),
        User(id=5, email='charles@demo.com', name='Charles Severance', role='professor',
             hashed_password=hashed_password, avatar=generate_avatar(random.randrange(10**5, 10**10)),
             age=48, gender='Male', address='6391 elgin St.celina Delaware 10299',
             post='Professor, School of Information', key_ompetency='Programming',
             skill_points=['Programming', 'Database design', 'Web development']),
    ]

    for user in users:
        db.session.add(user)
        db.session.commit()
        db.session.refresh(user)

    visitor = User(
        email='visitor@demo.com',
        role='student',
        name='Alice',
        gender='Female',
        hashed_password=hashed_password,
        avatar=generate_avatar(random.randrange(10**5, 10**10))
    )
    db.session.add(visitor)
    db.session.commit()
    db.session.refresh(visitor)

    courses = [
        Course(id=1, name='Computer Programming Course work', professor_id=4, online=True, school_year=2021, trimester=3,
            duration=50, lessons=4, progress=2, number_of_students=80,
            about='''This course will introduce the learner to the basics of the python programming environment, including fundamental python programming techniques such as lambdas, reading and manipulating csv files, and the numpy library. The course will introduce data manipulation and cleaning techniques using the popular python pandas data science library and introduce the abstraction of the Series and DataFrame as the central data structures for data analysis, along with tutorials on how to use functions such as groupby, merge, and pivot tables effectively. By the end of this course, students will be able to take tabular data, clean it, manipulate it, and run basic inferential statistical analyses. \n\nThis course should be taken before any of the other Applied Data Science with Python courses: Applied Plotting, Charting & Data Representation in Python, Applied Machine Learning in Python, Applied Text Mining in Python, Applied Social Network Analysis in Python.'''),
        Course(id=2, name='Interactive design Course work', professor_id=5, online=False, school_year=2021, trimester=4,
            duration=45, lessons=4, progress=0, number_of_students=231,
            about='''Master Python for a variety of cybersecurity tasks. This Specialization provides an application-driven introduction to using Python for cybersecurity.'''),
        Course(id=3, name='Database System Course work', professor_id=2, online=False, school_year=2021, trimester=2,
            duration=30, lessons=4, progress=1, number_of_students=125,
            about='''Build the Foundation for your Data Science career. Develop hands-on experience with Jupyter, Python, SQL. Perform Statistical Analysis on real data sets.'''),
        Course(id=4, name='Risk and Decision Course work', professor_id=3, online=True, school_year=2021, trimester=1,
            duration=40, lessons=4, progress=4, number_of_students=209,
            about='''To really understand what is special about Bitcoin, we need to understand how it works at a technical level. We’ll address the important questions about Bitcoin, such as:\n\nHow does Bitcoin work? What makes Bitcoin different? How secure are your Bitcoins? How anonymous are Bitcoin users? What determines the price of Bitcoins? Can cryptocurrencies be regulated? What might the future hold?\n\nAfter this course, you’ll know everything you need to be able to separate fact from fiction when reading claims about Bitcoin and other cryptocurrencies. You’ll have the conceptual foundations you need to engineer secure software that interacts with the Bitcoin network. And you’ll be able to integrate ideas from Bitcoin in your own projects.\n\nCourse Lecturers:\nArvind Narayanan, Princeton University\n\n\nAll the features of this course are available for free.  It does not offer a certificate upon completion.'''),
        Course(id=5, name='Security And Authentication Course work', professor_id=4, online=True, school_year=2021,trimester=3,
            duration=50, lessons=4, progress=2, number_of_students=80,
            about='''This course will introduce the learner to the basics of the python programming environment, including fundamental python programming techniques such as lambdas, reading and manipulating csv files, and the numpy library. The course will introduce data manipulation and cleaning techniques using the popular python pandas data science library and introduce the abstraction of the Series and DataFrame as the central data structures for data analysis, along with tutorials on how to use functions such as groupby, merge, and pivot tables effectively. By the end of this course, students will be able to take tabular data, clean it, manipulate it, and run basic inferential statistical analyses. \n\nThis course should be taken before any of the other Applied Data Science with Python courses: Applied Plotting, Charting & Data Representation in Python, Applied Machine Learning in Python, Applied Text Mining in Python, Applied Social Network Analysis in Python.'''),
        Course(id=6, name='Business Information System', professor_id=5, online=False, school_year=2021, trimester=4,
            duration=45, lessons=4, progress=0, number_of_students=231,
            about='''Master Python for a variety of cybersecurity tasks. This Specialization provides an application-driven introduction to using Python for cybersecurity.'''),

    ]
    for course in courses:
        db.session.add(course)
        db.session.commit()
        db.session.refresh(course)

    participants = [
        Participant(user_id=visitor.id, course_id=1),
        Participant(user_id=visitor.id, course_id=2),
        Participant(user_id=visitor.id, course_id=3),
        Participant(user_id=visitor.id, course_id=4),
        # Participant(user_id=visitor.id, course_id=5),
        # Participant(user_id=visitor.id, course_id=6),
    ]
    for participant in participants:
        db.session.add(participant)
        db.session.commit()
        db.session.refresh(participant)

    timetables = [
        Timetable(course_id=1, title='Fundamentals of Data Manipulation with Python', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''In this week you'll get an introduction to the field of data science, review common Python functionality and features which data scientists use, and be introduced to the Coursera Jupyter Notebook for the lectures. All of the course information on grading, prerequisites, and expectations are on the course syllabus, and you can find more information about the Jupyter Notebooks on our Course Resources page.'''),
        Timetable(course_id=1, title='Basic Data Processing with Pandas', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''In this week of the course you'll learn the fundamentals of one of the most important toolkits Python has for data cleaning and processing -- pandas. You'll learn how to read in data into DataFrame structures, how to query these structures, and the details about such structures are indexed.'''),
        Timetable(course_id=1, title='More Data Processing with Pandas', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''In this week you'll deepen your understanding of the python pandas library by learning how to merge DataFrames, generate summary tables, group data into logical pieces, and manipulate dates. We'll also refresh your understanding of scales of data, and discuss issues with creating metrics for analysis. The week ends with a more significant programming assignment.'''),
        Timetable(course_id=1, title='Answering Questions with Messy Data', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''In this week of the course you'll be introduced to a variety of statistical techniques such a distributions, sampling and t-tests. The week ends with two discussions of science and the rise of the fourth paradigm -- data driven discovery.'''),
        Timetable(course_id=1, title='Credential Access, discovery, lateral movement & collection',place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This course covers credential Access, discovery, lateral movement & collection.'''),
        Timetable(course_id=1, title='Python for Command-and-control, Exfiltration and Impact',place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(),about='''This course covers python for Command-and-control, Exfiltration and Impact.'''),

        Timetable(course_id=2, title='Introduction to Python for Cybersecurity', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This course it the first part of the Python for Cybersecurity Specialization. Learners will get an introduction and overview of the course format and learning objectives.'''),
        Timetable(course_id=2, title='Execution, persistence, privilege escalation and evasion', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This course is a continuation of Python for Cybersecurity. The topics covered are execution, persistence, privilege escalation and evasion.'''),
        Timetable(course_id=2, title='Credential Access, discovery, lateral movement & collection', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This course covers credential Access, discovery, lateral movement & collection.'''),
        Timetable(course_id=2, title='Python for Command-and-control, Exfiltration and Impact', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This course covers python for Command-and-control, Exfiltration and Impact.'''),
        Timetable(course_id=2, title='More Data Processing with Pandas', place='The second teaching building 604',
            state='not_started',start_time=datetime.now(), end_time=datetime.now(),about='''In this week you'll deepen your understanding of the python pandas library by learning how to merge DataFrames, generate summary tables, group data into logical pieces, and manipulate dates. We'll also refresh your understanding of scales of data, and discuss issues with creating metrics for analysis. The week ends with a more significant programming assignment.'''),
        Timetable(course_id=2, title='Answering Questions with Messy Data', place='The second teaching building 604',
            state='not_started',start_time=datetime.now(), end_time=datetime.now(),about='''In this week of the course you'll be introduced to a variety of statistical techniques such a distributions, sampling and t-tests. The week ends with two discussions of science and the rise of the fourth paradigm -- data driven discovery.'''),

        Timetable(course_id=3, title='Tools for Data Science', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''What are some of the most popular data science tools, how do you use them, and what are their features? In this course, you'll learn about Jupyter Notebooks, JupyterLab, RStudio IDE, Git, GitHub, and Watson Studio. You will learn about what each tool is used for, what programming languages they can execute, their features and limitations. With the tools hosted in the cloud on Skills Network Labs, you will be able to test each tool and follow instructions to run simple code in Python, R or Scala. To end the course, you will create a final project with a Jupyter Notebook on IBM Watson Studio and demonstrate your proficiency preparing a notebook, writing Markdown, and sharing your work with your peers.'''),
        Timetable(course_id=3, title='Python for Data Science, AI & Development', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''Kickstart your learning of Python for data science, as well as programming in general, with this beginner-friendly introduction to Python. Python is one of the world’s most popular programming languages, and there has never been greater demand for professionals with the ability to apply Python fundamentals to drive business solutions across industries. '''),
        Timetable(course_id=3, title='Python Project for Data Science', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This mini-course is intended to for you to demonstrate foundational Python skills for working with data. The completion of this course involves working on a hands-on project where you will develop a simple dashboard using Python.'''),
        Timetable(course_id=3, title='Statistics for Data Science with Python', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This Statistics for Data Science course is designed to introduce you to the basic principles of statistical methods and procedures used for data analysis. After completing this course you will have practical knowledge of crucial topics in statistics including  - data gathering, summarizing data using descriptive statistics, displaying and visualizing data, examining relationships between variables, probability distributions, expected values, hypothesis testing, introduction to ANOVA (analysis of variance), regression and correlation analysis. You will take a hands-on approach to statistical analysis using Python and Jupyter Notebooks – the tools of choice for Data Scientists and Data Analysts. '''),
        Timetable(course_id=3, title='Mechanics of Bitcoin', place='The second teaching building 604',
            state='not_started',start_time=datetime.now(), end_time=datetime.now(),about='''Learn how the individual components of the Bitcoin protocol make the whole system tick: transactions, script, blocks, and the peer-to-peer network.'''),
        Timetable(course_id=3, title='How to Store and Use Bitcoins', place='The second teaching building 604',
            state='not_started',start_time=datetime.now(), end_time=datetime.now(),about='''This week we'll explore how using Bitcoins works in practice: different ways of storing Bitcoin keys, security measures, and various types of services that allow you to trade and transact with bitcoins.'''),

        Timetable(course_id=4, title='Introduction to Crypto and Cryptocurrencies', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''Learn about cryptographic building blocks ("primitives") and reason about their security. Work through how these primitives can be used to construct simple cryptocurrencies.'''),
        Timetable(course_id=4, title='How Bitcoin Achieves Decentralization', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''Learn Bitcoin's consensus mechanism and reason about its security. Appreciate how security comes from a combination of technical methods and clever incentive engineering.'''),
        Timetable(course_id=4, title='Mechanics of Bitcoin', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''Learn how the individual components of the Bitcoin protocol make the whole system tick: transactions, script, blocks, and the peer-to-peer network.'''),
        Timetable(course_id=4, title='How to Store and Use Bitcoins', place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(), about='''This week we'll explore how using Bitcoins works in practice: different ways of storing Bitcoin keys, security measures, and various types of services that allow you to trade and transact with bitcoins.'''),
        Timetable(course_id=4, title='Python Project for Data Science', place='The second teaching building 604',state='not_started',
            start_time=datetime.now(), end_time=datetime.now(),about='''This mini-course is intended to for you to demonstrate foundational Python skills for working with data. The completion of this course involves working on a hands-on project where you will develop a simple dashboard using Python.'''),
        Timetable(course_id=4, title='Statistics for Data Science with Python',place='The second teaching building 604', state='not_started',
            start_time=datetime.now(), end_time=datetime.now(),about='''This Statistics for Data Science course is designed to introduce you to the basic principles of statistical methods and procedures used for data analysis. After completing this course you will have practical knowledge of crucial topics in statistics including  - data gathering, summarizing data using descriptive statistics, displaying and visualizing data, examining relationships between variables, probability distributions, expected values, hypothesis testing, introduction to ANOVA (analysis of variance), regression and correlation analysis. You will take a hands-on approach to statistical analysis using Python and Jupyter Notebooks – the tools of choice for Data Scientists and Data Analysts. '''),

    ]
    for timetable in timetables:
        db.session.add(timetable)
        db.session.commit()
        db.session.refresh(timetable)

def ensure_admin_account(app: Flask, db: SQLAlchemy):
    email = app.config['ADMIN_ACCOUNT']
    password = app.config['ADMIN_PASSWORD']
    user = db.session.query(User).filter(User.email == email).first()
    if not user is None:
        return False

    avatar = generate_avatar(email)
    hashed_password = generate_password_hash(password)

    user = User(
        id=1,
        email=email,
        role='admin',
        name='Administrator',
        hashed_password=hashed_password,
        avatar=avatar
    )
    db.session.add(user)
    db.session.commit()
    db.session.refresh(user)
    return True
